﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BudgetMealsModels.Entities;
using BudgetMealsModels.Abstract;
using BudgetMealsModels.Concrete;
using BudgetMealsUI.Models;
using System.Web.Security;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace BudgetMealsUI.Controllers
{
    public class RecipeController : Controller
    {
        private IRecipeRepository _repo;
        private IUserRepository userRepo;
        private ICommentRepository commentRepo;
        private int pageSize = 12;


        public ActionResult ShowTopRecipes()
        {
            IEnumerable<Recipe> recipes = _repo.Recipes.AsEnumerable().OrderByDescending(r => r.Rating).Take(10);
            return View(recipes);
        }
        public RecipeController(IRecipeRepository repository, IUserRepository userRepository, ICommentRepository commentRepository)
        {
            _repo = repository;
            userRepo = userRepository;
            commentRepo = commentRepository;

        }
        public ActionResult AllRecipes(string category, int Page=1)
        {
            List<Recipe> recipes = _repo.Recipes.ToList();
            if (category != null)
            {
                recipes = _repo.Recipes.Where(x => x.RecipeEthnicity == category || x.RecipeType == category).ToList();
            }
            ListViewModel<Recipe> LVM = new ListViewModel<Recipe>() { PageItems = recipes.OrderBy(x => x.Name).Skip(pageSize * (Page - 1)).Take(pageSize), Info = new PagingInfo() { CurrentPage = Page, ItemsPerPage = pageSize , TotalItems = recipes.Count } };
            return View(LVM);
        }
        public ActionResult ShowRecipe(int Id)
        {
            Recipe recipe = _repo.Recipes.FirstOrDefault(r=> r.RecipeID==Id);
            return View(recipe);
        }
        [Authorize]
        public ActionResult Delete(int Id, int userId, String redirectURL="~/Recipe/AllRecipes")
        {
            Recipe recipe = _repo.Recipes.FirstOrDefault(r => r.RecipeID == Id);
            User user = userRepo.Users.FirstOrDefault(u => u.UserID == userId);
            _repo.Delete(recipe, userId);
            return Redirect(redirectURL);

        }
        [Authorize]
        [HttpGet]
        public ActionResult Edit(int userId, int Id=0 )
        {
            Session["Images"] = null;
            Recipe recipe = _repo.Recipes.FirstOrDefault(r => r.RecipeID == Id);
            User user = userRepo.Users.FirstOrDefault(u => u.UserID == userId);
            if (user == null)
            {
                return RedirectToAction("Index", "Home");
            }
            if (recipe == null)
            {
                recipe = new Recipe();
                recipe.UserCreated = user.UserName;
                recipe.UserCreatedID = userId;
                recipe.Ingredients = new List<Ingredient>();
            }
            Session["Images"] = recipe.ImageGallery;
            return View(recipe);
        }

        [Authorize]
        [HttpPost]
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateInput(false)]
        public ActionResult Edit(Recipe recipe, int Ingred)
        {
            bool valid = true;
            if(String.IsNullOrWhiteSpace(recipe.Summary) || String.IsNullOrWhiteSpace(recipe.Instructions))
            {
                ModelState.AddModelError("", "Both summary and instructions are required.");
                return View(recipe);
            }
            if (Request["number"] != null && int.Parse(Request["number"]) == 0)
            {
                if (Ingred <= 0)
                {
                    if (recipe.RecipeID != 0)
                    {
                        Recipe r = _repo.Recipes.FirstOrDefault(ru => ru.RecipeID == recipe.RecipeID);
                        recipe.Ingredients = r.Ingredients;
                    }
                    ModelState.AddModelError(string.Empty, "There where no ingredients added must have at least 1");
                    valid = false;
                }
            }
            else
            {

            }
            for (int i = Ingred; i < int.Parse(Request["number"]); i++)
            {
                var name = Request["name" + i];
                var measurement = Request["measurement" + i];
                var cost = Request["cost" + i];

                if (name == string.Empty || measurement == string.Empty || cost == string.Empty || System.Text.RegularExpressions.Regex.IsMatch(cost, "(\\^\\d*\\.\\d{2}\\$)|(\\^\\d*\\$)"))
                {
                    ModelState.AddModelError(string.Empty, "One or more ingredients are invalid.");

                    valid = false;
                }
            }
            if (recipe.ServingSize < 1)
            {
                ModelState.AddModelError(string.Empty, "The serving size must be a whole number above 0");
                valid = false;
            }
            if (valid)
            {
                List<Ingredient> Ingredients = new List<Ingredient>();
                if (recipe.RecipeID != 0)
                {
                    Recipe r = _repo.Recipes.FirstOrDefault(ru => ru.RecipeID == recipe.RecipeID);
                    Ingredients = r.Ingredients;
                }
                for (int i = Ingred; i < int.Parse(Request["number"]); i++)
                {
                    Ingredients.Add(new Ingredient() { Name = Request["name" + i], Measurement = Request["measurement" + i], Cost = (double.Parse(Request["cost" + i])) });
                }
                recipe.Ingredients = Ingredients;
                recipe.Instructions = recipe.Instructions.Replace("\n", "<br/>");
                int id = _repo.Edit(recipe, (int)Session["CurrentUser"]);
                return RedirectToAction("AddImage", "Recipe", new{id = id});
            }
            else
            {
                return View(recipe);
            }
        }

        public ActionResult Related(int recipeId)
        {
            var recipes = _repo.Recipes;
            var searchRecipe = _repo.Recipes.FirstOrDefault(r => r.RecipeID == recipeId);
            var related = new List<Recipe>();

            if (searchRecipe.Ingredients != null)
                foreach (var recipe in recipes.ToList())
                {
                    var test = recipe.Summary;
                    if (recipe.Ingredients != null && recipe != searchRecipe)
                        foreach (var ingredient in recipe.Ingredients)
                        {
                            if (searchRecipe.Ingredients.Contains(ingredient))
                            {
                                related.Add(recipe);
                                continue;
                            }
                        }
                }

            return View(related.OrderBy(r => r.RecipeID).Take(3));
        }
        /*public ActionResult Related(Recipe recipe)
        {
            IEnumerable<Recipe> relatedRecipes = _repo.Recipes.Where(r => r.Related(recipe));

            return View(recipe);
        }*/
        public ActionResult SelectorList(string searchString, bool searchUserRecipes, int page = 1)
        {
            var relatedRecipes = _repo.Recipes.Where(r => r.Name.Contains(searchString));
            var itemsPerPage = 4;
            var recipes = relatedRecipes;
            
            if (searchUserRecipes)
            {
                var userID = (int) Session["CurrentUser"];
                
                recipes = recipes.Where(r => r.User.UserID == userID);
            }

            recipes = recipes.OrderBy(r => r.RecipeID).Skip((page - 1) * itemsPerPage).Take(itemsPerPage);

            var viewModel = new RecipeSelectorViewModel
            {
                PagingInfo = new PagingInfo 
                { 
                    CurrentPage = page, 
                    ItemsPerPage = itemsPerPage, 
                    TotalItems = relatedRecipes.Count(),
                },
                Recipes = recipes,
                SearchString = searchString,
                SearchUserRecipes = searchUserRecipes
            };
            return PartialView(viewModel);
        }
        public ActionResult AddComment(int commentId, int recipeId)
        {
            Recipe recipe = _repo.Recipes.FirstOrDefault(x => x.RecipeID == recipeId);
            Comment comment = commentRepo.Comments.FirstOrDefault(c => c.CommentID == commentId);
            if (comment == null)
            {
                comment = new Comment();
                comment.Recipe = recipe;
                comment.Review = Request["Review"];
                comment.UserCreated = (String)Session["CurrentUserName"];
                comment.UserCreatedID = (int)Session["CurrentUser"];
                if (Request["RecipeRating"] != "")
                {
                    comment.RecipeRating = Convert.ToInt16(Request["RecipeRating"]);
                    if (ModelState.IsValid)
                    {
                        _repo.AddComment(comment);
                    }
                }
            }
            return View("ShowRecipe", recipe);
        }
        public ActionResult AddImage(int id)
        {
            ViewBag.recipeId = id;
            if (id != 0)
            {
                Session["Images"] = _repo.Recipes.FirstOrDefault(x => x.RecipeID == id).ImageGallery;
            }
            return View();
        }
        [HttpPost]
        public ActionResult AddImage(HttpPostedFileBase image, String redirectURL, int id)
        {
            ViewBag.recipeId = id;
            if (image == null || image.ContentType == "image/jpeg" || image.ContentType == "image/jpg" || image.ContentType == "image/png")
            {
                List<BudgetMealsModels.Entities.Image> ImageGallery = (List<BudgetMealsModels.Entities.Image>)Session["Images"];
                if (ImageGallery == null)
                {
                    ImageGallery = new List<BudgetMealsModels.Entities.Image>();
                }
                if (image != null)
                {
                    BudgetMealsModels.Entities.Image i = new BudgetMealsModels.Entities.Image();
                    System.Drawing.Image beginImage = System.Drawing.Image.FromStream(image.InputStream);
                    Bitmap resizedImage = ResizeImage(beginImage);
                    i.ImageMimeType = image.ContentType;
                    i.ImageData = (byte[])System.ComponentModel.TypeDescriptor.GetConverter(resizedImage).ConvertTo(resizedImage, typeof(byte[]));
                    ImageGallery.Add(i);
                    Session["Images"] = ImageGallery;
                    image.InputStream.Close();
                }
            }
            else
            {
                ModelState.AddModelError("", "Invalid file extension, must be .jpeg, .jpg, or .png");
            }
            return View();

        }

        public ActionResult FinishEditing(int id)
        {
            Recipe recipe = _repo.Recipes.FirstOrDefault(x => x.RecipeID == id);
            recipe.ImageGallery = (List<BudgetMealsModels.Entities.Image>)Session["Images"];
            _repo.Edit(recipe, (int)Session["CurrentUser"]);
            return RedirectToActionPermanent("Profile", "User", new { id= (int)Session["CurrentUser"]});
        }
        public ActionResult DeleteImage(String redirectURL,int imageID = -1)
        {
            if (imageID >= 0)
            {
                List<BudgetMealsModels.Entities.Image> Images = (List<BudgetMealsModels.Entities.Image>)Session["Images"];
                if (Images != null && Images.Count > imageID)
                {
                    Images.RemoveAt(imageID);
                    Session["Images"] = Images;
                }
            }
            return Redirect(redirectURL);
        }
        public FileContentResult GetImage(int recipeId, int image)
        {
            Recipe recipe = _repo.Recipes.FirstOrDefault(r => r.RecipeID == recipeId);

            if (recipe != null && recipe.ImageGallery != null && recipe.ImageGallery.Count > 0)
            {
                return File(recipe.ImageGallery[image].ImageData, recipe.ImageGallery[image].ImageMimeType);
            }
            else
            {
                using (var stream = new FileStream(Server.MapPath("~/Content/Images/Misc/NoImage.png"), FileMode.Open, FileAccess.Read))
                {
                    var data = new byte[stream.Length];

                    stream.Read(data, 0, (int)stream.Length);

                    return File(data, "png");
                }

            }
        }
        public FileContentResult Display(int imageID)
        {
            if (Session["Images"] != null)
            {
                BudgetMealsModels.Entities.Image image = ((List<BudgetMealsModels.Entities.Image>)Session["Images"])[imageID];
                return File(image.ImageData, image.ImageMimeType);
            }
            return null;
        }

        public Bitmap ResizeImage(System.Drawing.Image srcImage)
        {
            int newHeight = FindNewHeightOrWidth(srcImage.Height);
            int newWidth = FindNewHeightOrWidth(srcImage.Width);
            Bitmap newImage = new Bitmap(newWidth, newHeight);
            using (Graphics gr = Graphics.FromImage(newImage))
            {
                gr.SmoothingMode = SmoothingMode.AntiAlias;
                gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
                gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
                gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
            }
            return newImage;
        }

        public int FindNewHeightOrWidth(double value)
        {
            while (value > 600)
            {
                value = value / 1.1;
            }
            return (int)Math.Round(value);
        }
    }


}
